package com.yonyou.pmclouds.statistic.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.yonyou.iuap.print.client.utils.JsonUtil;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.ChineseStringUtils;
import com.yonyou.pmclouds.basecom.view.DisableWrap;
import com.yonyou.pmclouds.businessobject.util.BusinessObjectConsts;
import com.yonyou.pmclouds.enterprise.entity.EnterpriseInfo;
import com.yonyou.pmclouds.organization.rmiitf.OrganizationQuery;
import com.yonyou.pmclouds.outter.enterprise.EnterpriseInfoQuery;
import com.yonyou.pmclouds.outter.role.UserRoleInfoQuery;
import com.yonyou.pmclouds.outter.user.UserInfoQuery;
import com.yonyou.pmclouds.statistic.entity.SignInListReportVO;
import com.yonyou.pmclouds.statistic.entity.SignInListReportViewVO;
import com.yonyou.pmclouds.statistic.entity.SignInUserReportVO;
import com.yonyou.pmclouds.statistic.rmiitf.SignInStatisticService;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 签到报表
 *
 * @author th
 * @date 2019/7/20 10:14
 */
@RestController
@RequestMapping("/signInStatistic")
public class SignInStatisticController {

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private SignInStatisticService signInStatisticService;
    @Autowired
    private EnterpriseInfoQuery enterpriseInfoQuery;
    @Autowired
    private UserInfoQuery userInfoQuery;
    @Autowired
    private UserRoleInfoQuery userRoleInfoQuery;
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private OrganizationQuery organizationQuery;

    @GetMapping("/queryListByProjects")
    public List<SignInListReportViewVO> querySignInListByProjects(
            @RequestParam(value = "orgId", required = false) String orgId,
            @RequestParam(value = "projectIds[]", required = false) String[] projectIds,
            @RequestParam("timeStart") long timeStart,
            @RequestParam("timeEnd") long timeEnd) throws BusinessException {
        String[] orgIds = null;
        if (ArrayUtils.isEmpty(projectIds))
            orgIds = getValidOrg(orgId);
        List<SignInListReportViewVO> results = signInStatisticService.queryListOfProjects(RuntimeEnvironment.getTenantId(),
                orgIds, projectIds, timeStart, timeEnd);
        if (results != null && results.size() > 0) {
            setEnterpriseAndUserNames(results, SignInListReportViewVO.PK_PROJECT);
        }

        return results;
    }

    @GetMapping("/queryUserByProject")
    public List<SignInUserReportVO> queryUserSignInsByProject(
            @RequestParam(value = "userId") String userId,
            @RequestParam(value = "projectId") String projectId,
            @RequestParam("timeStart") long timeStart,
            @RequestParam("timeEnd") long timeEnd) throws BusinessException {
        List<SignInUserReportVO> results = signInStatisticService.queryUserSignInOfProject(RuntimeEnvironment.getTenantId(),
                userId, projectId, timeStart, timeEnd);

        return results;
    }

    @GetMapping("/queryListByEnts")
    public List<SignInListReportViewVO> querySignInListByEnterprises(
            @RequestParam(value = "orgId", required = false) String orgId,
            @RequestParam("timeStart") long timeStart,
            @RequestParam("timeEnd") long timeEnd) throws BusinessException {
        String[] orgIds = getValidOrg(orgId);
        List<SignInListReportViewVO> results = signInStatisticService.queryListOfEnterprises(RuntimeEnvironment.getTenantId(),
                orgIds, timeStart, timeEnd);
        if (results != null && results.size() > 0) {
            setEnterpriseAndUserNames(results, SignInListReportViewVO.PK_ENTERPRISE);
            // 按照企业名称排序
            Collections.sort(results, new Comparator<SignInListReportViewVO>() {
                @Override
                public int compare(SignInListReportViewVO o1, SignInListReportViewVO o2) {
                    if (o1 == o2)
                        return 0;
                    if (o1 == null)
                        return 1;
                    if (o2 == null)
                        return -1;
                    return ChineseStringUtils.compareInDict(o1.getEnterpriseName(), o2.getEnterpriseName());
                }
            });
        }

        return results;
    }

    @GetMapping("/queryUserByEnt")
    public List<SignInUserReportVO> queryUserSignInsByEnt(
            @RequestParam(value = "orgId", required = false) String orgId,
            @RequestParam(value = "userId") String userId,
            @RequestParam(value = "enterpriseId") String enterpriseId,
            @RequestParam("timeStart") long timeStart,
            @RequestParam("timeEnd") long timeEnd) throws BusinessException {
        String[] orgIds = getValidOrg(orgId);
        List<SignInUserReportVO> results = signInStatisticService.queryUserSignInOfEnt(RuntimeEnvironment.getTenantId(),
                orgIds, enterpriseId, userId, timeStart, timeEnd);

        return results;
    }

    @RequestMapping("/printListByProjects")
    @DisableWrap
    public Map<String, Object[]> printSignInListByProjects(HttpServletRequest request) throws BusinessException {
        String orgId = (String) JsonUtil.jsonToMap(request.getParameter("params")).get("orgId");
        List<String> projectIdList = (List<String>) JsonUtil.jsonToMap(request.getParameter("params")).get("projectIds");
        long timeStart = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeStart");
        long timeEnd = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeEnd");

        String[] orgIds = null;
        if (projectIdList == null || projectIdList.size() == 0)
            orgIds = getValidOrg(orgId);
        List<SignInListReportViewVO> viewVOS = signInStatisticService.queryListOfProjects(RuntimeEnvironment.getTenantId(),
                orgIds, projectIdList == null ? null : projectIdList.toArray(new String[projectIdList.size()]), timeStart, timeEnd);

        if (viewVOS != null && viewVOS.size() > 0) {
            setEnterpriseAndUserNames(viewVOS, SignInListReportViewVO.PK_PROJECT);
        }

        SignInListReportVO[] reportVOS = getReportsByViewVOs(viewVOS);
        Map<String, Object[]> result = new HashMap<>();
        result.put(BusinessObjectConsts.PM_SIGNIN_PROJECTLIST_REPORT, viewVOS.toArray(new SignInListReportViewVO[viewVOS.size()]));
        result.put(BusinessObjectConsts.PM_SIGNIN_PROJECTLIST_REPORT_B, reportVOS);

        return result;
    }

    @RequestMapping("/printUserByProject")
    @DisableWrap
    public Map<String, Object[]> printUserSignInsByProject(HttpServletRequest request) throws BusinessException {
        String userId = (String) JsonUtil.jsonToMap(request.getParameter("params")).get("userId");
        String projectId = (String) JsonUtil.jsonToMap(request.getParameter("params")).get("projectId");
        long timeStart = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeStart");
        long timeEnd = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeEnd");

        List<SignInUserReportVO> userReportVOS = signInStatisticService.queryUserSignInOfProject(RuntimeEnvironment.getTenantId(),
                userId, projectId, timeStart, timeEnd);

        Map<String, Object[]> results = new HashMap<>();
        results.put(BusinessObjectConsts.PM_SIGNIN_USER_PROJECT_REPORT, userReportVOS.toArray(new SignInUserReportVO[userReportVOS.size()]));

        return results;
    }

    @RequestMapping("/printListByEnts")
    @DisableWrap
    public Map<String, Object[]> printSignInListByEnterprises(HttpServletRequest request) throws BusinessException {
        String orgId = (String) JsonUtil.jsonToMap(request.getParameter("params")).get("orgId");
        long timeStart = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeStart");
        long timeEnd = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeEnd");

        String[] orgIds = getValidOrg(orgId);
        List<SignInListReportViewVO> viewVOS = signInStatisticService.queryListOfEnterprises(RuntimeEnvironment.getTenantId(),
                orgIds, timeStart, timeEnd);
        if (viewVOS != null && viewVOS.size() > 0) {
            setEnterpriseAndUserNames(viewVOS, SignInListReportViewVO.PK_ENTERPRISE);
            // 按照企业名称排序
            Collections.sort(viewVOS, new Comparator<SignInListReportViewVO>() {
                @Override
                public int compare(SignInListReportViewVO o1, SignInListReportViewVO o2) {
                    if (o1 == o2)
                        return 0;
                    if (o1 == null)
                        return 1;
                    if (o2 == null)
                        return -1;
                    return ChineseStringUtils.compareInDict(o1.getEnterpriseName(), o2.getEnterpriseName());
                }
            });
        }

        SignInListReportVO[] reportVOS = getReportsByViewVOs(viewVOS);

        Map<String, Object[]> results = new HashMap<>();
        results.put(BusinessObjectConsts.PM_SIGNIN_ENTERPRISELIST_REPORT, viewVOS.toArray(new SignInListReportViewVO[viewVOS.size()]));
        results.put(BusinessObjectConsts.PM_SIGNIN_ENTERPRISELIST_REPORT_B, reportVOS);

        return results;
    }

    @RequestMapping("/printUserByEnt")
    @DisableWrap
    public Map<String, Object[]> printUserSignInsByEnt(HttpServletRequest request) throws BusinessException {
        String orgId = (String) JsonUtil.jsonToMap(request.getParameter("params")).get("orgId");
        String userId = (String) JsonUtil.jsonToMap(request.getParameter("params")).get("userId");
        String enterpriseId = (String) JsonUtil.jsonToMap(request.getParameter("params")).get("enterpriseId");
        long timeStart = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeStart");
        long timeEnd = (long) JsonUtil.jsonToMap(request.getParameter("params")).get("timeEnd");
        String[] orgIds = getValidOrg(orgId);

        List<SignInUserReportVO> reportVOS = signInStatisticService.queryUserSignInOfEnt(RuntimeEnvironment.getTenantId(),
                orgIds, enterpriseId, userId, timeStart, timeEnd);

        Map<String, Object[]> results = new HashMap<>();
        results.put(BusinessObjectConsts.PM_SIGNIN_USER_ENTERPRISE_REPORT, reportVOS.toArray(new SignInUserReportVO[reportVOS.size()]));

        return results;
    }

    /**
     * 获取列表所有的考勤记录（打印）
     *
     * @param viewVOS
     * @return
     */
    private SignInListReportVO[] getReportsByViewVOs(List<SignInListReportViewVO> viewVOS) {
        List<SignInListReportVO> results = new ArrayList<>();
        if (viewVOS == null || viewVOS.size() == 0)
            return new SignInListReportVO[0];
        for (SignInListReportViewVO viewVo : viewVOS) {
            results.addAll(viewVo.getReportVO());
        }

        return results.toArray(new SignInListReportVO[results.size()]);
    }

    /**
     * 获取有效的组织，当组织为空时查询用户有权限的组织
     *
     * @param orgId
     * @return
     */
    private String[] getValidOrg(String orgId) throws BusinessException {
        String[] orgIds;
        if (StringUtils.isEmpty(orgId)) {
            // 组织为空，查询用户有权限的组织
            orgIds = getPermOrgByUser();
        } else {
            orgIds = new String[1];
            orgIds[0] = orgId;
        }

        return orgIds;
    }

    /**
     * 获取用户有权限的组织
     *
     * @return
     */
    private String[] getPermOrgByUser() throws BusinessException {
        String pkTenant = RuntimeEnvironment.getTenantId();
        String pkUser = RuntimeEnvironment.getLoginUserId();
        String[] pkRoles = userRoleInfoQuery.getUserRoles(pkUser, pkTenant);
        String[] orgIds = organizationQuery.queryOrgIdsByRoles(pkTenant, pkRoles);

        return orgIds;
    }

    /**
     * 设置企业名、用户名
     *
     * @param results
     * @param groupField
     */
    private void setEnterpriseAndUserNames(List<SignInListReportViewVO> results, String groupField) {
        Set<String> pkEnts = new HashSet<>();
        Set<String> pkUsers = new HashSet<>();
        for (SignInListReportViewVO viewVo : results) {
            if (SignInListReportViewVO.PK_ENTERPRISE.equals(groupField)) {
                if (StringUtils.isNotEmpty(viewVo.getPkEnterprise()))
                    pkEnts.add(viewVo.getPkEnterprise());
            }
            if (viewVo.getReportVO() != null) {
                for (SignInListReportVO reportVO : viewVo.getReportVO()) {
                    if (SignInListReportViewVO.PK_PROJECT.equals(groupField) && StringUtils.isNotEmpty(reportVO.getPkEnterprise()))
                        pkEnts.add(reportVO.getPkEnterprise());
                    if (StringUtils.isNotEmpty(reportVO.getPkUser()))
                        pkUsers.add(reportVO.getPkUser());
                }
            }
        }

        Map<String, EnterpriseInfo> pkToEnter = queryEnterpriseNamesByIds(pkEnts.toArray(new String[pkEnts.size()]));
        Map<String, String> pkToUserName = queryUserNamesByIds(pkUsers.toArray(new String[pkUsers.size()]));

        for (SignInListReportViewVO viewVo : results) {
            if (SignInListReportViewVO.PK_ENTERPRISE.equals(groupField)) {
                if (StringUtils.isNotEmpty(viewVo.getPkEnterprise()) && pkToEnter.get(viewVo.getPkEnterprise()) != null)
                    viewVo.setEnterpriseName(pkToEnter.get(viewVo.getPkEnterprise()).getName());
            }
            if (viewVo.getReportVO() != null) {
                for (SignInListReportVO reportVO : viewVo.getReportVO()) {
                    if (StringUtils.isNotEmpty(reportVO.getPkEnterprise()) && pkToEnter.get(reportVO.getPkEnterprise()) != null)
                        reportVO.setEnterpriseName(pkToEnter.get(reportVO.getPkEnterprise()).getName());
                    if (StringUtils.isNotEmpty(reportVO.getPkUser()))
                        reportVO.setUserName(pkToUserName.get(reportVO.getPkUser()));
                }
            }
        }
    }

    /**
     * 根据用户id查询用户名称，如果查询数量大于1000，则分批次查询
     *
     * @param ids
     * @return
     */
    private Map<String, String> queryUserNamesByIds(String[] ids) {
        if (ArrayUtils.isEmpty(ids))
            return new HashMap<>();
        Map<String, String> results = new HashMap<>();
        if (ids.length < 1000) {
            results = userInfoQuery.queryUserNames(ids);
        } else {
            int count = ids.length / 1000;
            List<String> idList = Arrays.asList(ids);
            Map<String, String> currQuery;
            for (int i = 0; i < count; i++) {
                currQuery = userInfoQuery.queryUserNames(idList.subList(i * 1000, i * 1000 + 1000).toArray(new String[1000]));
                results.putAll(currQuery);
            }
            if (ids.length % 1000 > 0) {
                currQuery = userInfoQuery.queryUserNames(idList.subList(count * 1000, idList.size()).toArray(new String[0]));
                results.putAll(currQuery);
            }
        }

        return results;
    }

    /**
     * 根据企业id查询企业名称，如果查询数量大于1000，则分批次查询
     *
     * @param ids
     * @return
     */
    private Map<String, EnterpriseInfo> queryEnterpriseNamesByIds(String[] ids) {
        if (ArrayUtils.isEmpty(ids))
            return new HashMap<>();
        Map<String, EnterpriseInfo> results = new HashMap<>();
        if (ids.length < 1000) {
            results = enterpriseInfoQuery.queryEnterpriseByIds(ids);
        } else {
            int count = ids.length / 1000;
            List<String> idList = Arrays.asList(ids);
            Map<String, EnterpriseInfo> currQuery;
            for (int i = 0; i < count; i++) {
                currQuery = enterpriseInfoQuery.queryEnterpriseByIds(idList.subList(i * 1000, i * 1000 + 1000).toArray(new String[1000]));
                results.putAll(currQuery);
            }
            if (ids.length % 1000 > 0) {
                currQuery = enterpriseInfoQuery.queryEnterpriseByIds(idList.subList(count * 1000, idList.size()).toArray(new String[0]));
                results.putAll(currQuery);
            }
        }

        return results;
    }


}
